package itsm.isperp.module.service.problem;

import itsm.isperp.framework.data.dialect.DialectFactory;
import itsm.isperp.framework.service.BaseService;
import itsm.isperp.framework.utils.HibernateUUIDGenerator;
import itsm.isperp.framework.web.response.ResultMessage;
import itsm.isperp.module.entity.problem.ProbAutoTriggerRule;
import itsm.isperp.module.entity.problem.ProbProblem;
import itsm.isperp.module.repository.problem.ProbAutoTriggerRuleMapper;
import itsm.isperp.module.service.problem.rule.Counter;
import itsm.isperp.workflow.service.BpmProcessRunService;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import me.chanjar.weixin.common.util.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jdbc.support.DatabaseType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

/**
 * 服务
 * 
 * @author lizx
 * @date 2014-11-16 15:07
 */
@Service
public class ProbAutoTriggerRuleService extends
		BaseService<ProbAutoTriggerRule> {

	@Autowired
	protected ProbAutoTriggerRuleMapper probAutoTriggerRuleMapper;

	@Autowired
	ProbProblemService probProblemService;

	@Autowired
	BpmProcessRunService bpmProcessRunService;

	@Override
	public ProbAutoTriggerRuleMapper getRepository() {
		return this.probAutoTriggerRuleMapper;
	}

	@Autowired
	protected JdbcTemplate jdbcTemplate;

	/**
	 * 
	 * 
	 */
	public void generalProblemByRule() {
		// 获取所有规则
		List<ProbAutoTriggerRule> list = this.findAll();

		for (ProbAutoTriggerRule rule : list) {
			// 生成问题并排除重复项；根据内容排除
			generalProblemByRule(rule);
		}

	}

	private String generalRuleSql(ProbAutoTriggerRule rule) {
		// 生成数据库语句
		String sql = "   FROM icd_incident a ";

		String queryField = "";
		Set<String> grouBySet = new HashSet<>();

		boolean useCi = true, useIncidentCategory = true;

		String queryCiSql = "";
		String whereSql = "";

		if ("同一类型".equals(rule.getCiType())) {

			queryCiSql += " INNER JOIN conf_ci_use_relation cr INNER JOIN conf_ci c ON cr.ci_id=c.id ";

			whereSql += " AND cr.relation_type='incidentProcess'";

			grouBySet.add("c.conf_category_id");

		} else if ("指定类型".equals(rule.getCiType())) {
			queryCiSql += " INNER JOIN conf_ci_use_relation cr INNER JOIN conf_ci c ON cr.ci_id=c.id ";

			whereSql += " AND relation_type='incidentProcess' AND c.conf_category_id='"
					+ rule.getCiCategory() + "' ";

			grouBySet.add("c.conf_category_id");

		} else if ("同一资产".equals(rule.getCiType())) {

			queryCiSql += " INNER JOIN conf_ci_use_relation cr ON a.id=cr.relation_id ";

			whereSql += " AND cr.relation_type='incidentProcess'";

			grouBySet.add("cr.ci_id");

		} else {
			useIncidentCategory = false;
		}

		String queryIncidentCategorySql = " ";
		if ("同一类型".equals(rule.getIncidentType())) {

			grouBySet.add("a.icd_category_id");

		} else if ("指定类型".equals(rule.getIncidentType())) {
			whereSql += " AND  a.icd_category_id = '"
					+ rule.getIncidentCategory() + "' ";

			grouBySet.add("a.icd_category_id");

		} else {
			useIncidentCategory = false;
		}if ("相同标题".equals(rule.getIncidentTitleType())) {
			grouBySet.add("a.title");

		} else if ("包含关键字".equals(rule.getIncidentTitleType())) {

			String[] titles = rule.getIncidentTitleKey().split("#");

			for (String str : titles) {
				str = str.trim();
				if (StringUtils.isNotEmpty(str)) {
					whereSql += " AND  a.title LIKE '%" + str + "%' ";
				}
			}

		}

		if (useCi) {
			sql += queryCiSql;
		}

		if (useIncidentCategory) {
			sql += queryIncidentCategorySql;
		}

		if (StringUtils.isNotBlank(rule.getIncidentSatisfication())) {
			whereSql += " AND a.satisfaction='"
					+ rule.getIncidentSatisfication() + "' ";
		}

		if (StringUtils.isNotBlank(rule.getIncidentPriority())) {
			whereSql += " AND a.priority_name='" + rule.getIncidentPriority()
					+ "' ";

		}
		if (StringUtils.isNotBlank(rule.getIncidentFilterSql())) {
			whereSql += " AND " + rule.getIncidentFilterSql();
		}

		whereSql += " AND a.icd_category_id IS NOT NULL  AND NOT EXISTS(SELECT bp.id FROM bpm_process_relation bp WHERE bp.from_id=a.id) ";

		String queryTimes = "";
		if (rule.getTimeDistance() > 0) {

			if (DialectFactory.getDatabaseType() == DatabaseType.MYSQL) {
				queryTimes += " WHERE DATEDIFF(NOW(),a.create_date)<="
						+ rule.getTimeDistance();
			} else {
				queryTimes += " WHERE ROUND(TO_NUMBER(SYSDATE,a.create_date))<="
						+ rule.getTimeDistance();
			}
		} else {
			return null;
		}

		if (grouBySet.size() > 0) {
			for (String s : grouBySet) {
				queryField += "+" + s;
			}

			queryField = queryField.substring(1);

			queryField += " AS akey,";
		}
		queryField += "a.id";

		if ("类似标题".equals(rule.getIncidentTitleType())) {
			queryField += ",a.title";
		}

		sql = "SELECT " + queryField + sql + "  " + queryTimes + whereSql;

		return sql;
	}

	public ResultMessage checkRule(String id) {

		try {
			ProbAutoTriggerRule rule = this.findOne(id);

			String sql = this.generalRuleSql(rule);

			sql = DialectFactory.getDialect().getLimitString(sql);

			jdbcTemplate.queryForList(sql);

			return ResultMessage.success();
		} catch (Exception ex) {
			return ResultMessage.failure(ex.getMessage());
		}

	}

	public void generalProblemByRule(ProbAutoTriggerRule rule) {

		String sql = this.generalRuleSql(rule);

		List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);

		Map<String, Counter> icds = null;

		if ("类似标题".equals(rule.getIncidentTitleType())) {

			Map<String, Object> r1 = result.get(0);
			if (r1.size() == 2) {
				icds = ProbAutoTriggerRulePaser.paser2(result, rule);
			} else {
				icds = ProbAutoTriggerRulePaser.paser3(result, rule);
			}

		} else {
			icds = ProbAutoTriggerRulePaser.paser(result, rule);
		}
		// 1、创建一个问题
		// 2、批量将事件与问题进行关联
		for (String k : icds.keySet()) {

			Counter c = icds.get(k);
			ProbProblem p = new ProbProblem();
			p.setTitle(rule.getContentsTemplate());
			p.setDescription(rule.getContentsTemplate());

			p.setRequestDate(new Timestamp(new Date().getTime()));
			p.setRequester("admin");
			p.setRequesterName("系统管理员");
			// p.setProjectId(projectId);

			probProblemService.saveOrUpdate(p);

			try {
				bpmProcessRunService.startProcess("admin", "problemProcess",
						p.getId(), "自动发起");

				// 取得processId，插件流程关联

				List<Object[]> args = new ArrayList<>();

				for (String icdId : c.getList()) {
					Object[] arg = new Object[5];
					arg[0] = HibernateUUIDGenerator.generate();
					arg[1] = icdId;
					arg[2] = p.getId();
					arg[3] = "admin";
					arg[4] = "系统管理员";
					args.add(arg);
				}

				jdbcTemplate
						.batchUpdate(
								"INSERT INTO bpm_process_relation(id,from_id,to_id,creator,creator_name) VALUES(?,?,?,?,?)",
								args);

			} catch (SQLException e) {
				// 记录失败信息到数据库
				System.out.println(e);

			}

		}

	}
}
